package com.ittao.taoaicodemother.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.ittao.taoaicodemother.exception.BusinessException;
import com.ittao.taoaicodemother.exception.ErrorCode;
import com.ittao.taoaicodemother.mapper.VipRedeemCodeMapper;
import com.ittao.taoaicodemother.model.dto.vip.VipRedeemCodeQueryRequest;
import com.ittao.taoaicodemother.model.dto.vip.VipRedeemCodeUpdateRequest;
import com.ittao.taoaicodemother.model.entity.User;
import com.ittao.taoaicodemother.model.entity.VipRedeemCode;
import com.ittao.taoaicodemother.model.enums.UserRoleEnum;
import com.ittao.taoaicodemother.model.enums.VipRedeemCodeStatusEnum;
import com.ittao.taoaicodemother.model.vo.user.LoginUserVO;
import com.ittao.taoaicodemother.model.vo.vip.VipRedeemCodeVO;
import com.ittao.taoaicodemother.service.UserService;
import com.ittao.taoaicodemother.service.VipRedeemCodeService;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * VIP兑换码 服务层实现（集中所有VIP业务）。
 *
 * @author <a href="https://gitee.com/it-heima-ht">程序员 Tao</a>
 */
@Slf4j
@Service
public class VipRedeemCodeServiceImpl extends ServiceImpl<VipRedeemCodeMapper, VipRedeemCode> implements VipRedeemCodeService {

    @Resource
    private UserService userService;

    /**
     * 批量生成兑换码
     * @param count 生成数量，1-100
     * @param validUntil 有效期截止时间
     * @param vipDuration VIP有效期天数，为空时默认365天
     * @param remark 备注
     * @return 生成的兑换码列表
     */
    @Override
    public List<VipRedeemCode> generateRedeemCodes(Integer count, LocalDateTime validUntil, Integer vipDuration, String remark) {
        if (count == null || count <= 0 || count > 100) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "生成数量必须在1-100之间");
        }
        if (validUntil == null || validUntil.isBefore(LocalDateTime.now())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "有效期必须大于当前时间");
        }

        // 如果未传入VIP有效期天数，默认365天
        int actualVipDuration = (vipDuration != null && vipDuration > 0) ? vipDuration : 365;

        // 验证VIP有效期合理性（1天到10年）
        if (actualVipDuration > 3650) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "VIP有效期必须在1-3650天之间");
        }

        List<VipRedeemCode> redeemCodes = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            VipRedeemCode redeemCode = VipRedeemCode.builder()
                    .code(generateUniqueCode())
                    .status(VipRedeemCodeStatusEnum.UNUSED.getValue())
                    .validUntil(validUntil)
                    .vipDuration(actualVipDuration)  // 使用传入的VIP有效期天数
                    .remark(remark)
                    .createTime(LocalDateTime.now())
                    .updateTime(LocalDateTime.now())
                    .build();
            redeemCodes.add(redeemCode);
        }

        boolean result = this.saveBatch(redeemCodes);
        if (!result) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "批量生成兑换码失败");
        }

        log.info("成功生成 {} 个兑换码，VIP有效期：{}天", count, actualVipDuration);
        return redeemCodes;
    }

    /**
     * 构建查询条件
     * @param queryRequest
     * @return
     */
    @Override
    public QueryWrapper getQueryWrapper(VipRedeemCodeQueryRequest queryRequest) {
        if (queryRequest == null) {
            return new QueryWrapper();
        }

        QueryWrapper queryWrapper = new QueryWrapper();

        if (StrUtil.isNotBlank(queryRequest.getCode())) {
            queryWrapper.like("code", queryRequest.getCode());
        }

        if (StrUtil.isNotBlank(queryRequest.getStatus())) {
            queryWrapper.eq("status", queryRequest.getStatus());
        }

        if (StrUtil.isNotBlank(queryRequest.getUsedBy())) {
            queryWrapper.like("usedBy", queryRequest.getUsedBy());
        }

        // 添加创建时间范围查询
        if (queryRequest.getCreateTimeStart() != null) {
            queryWrapper.ge("createTime", queryRequest.getCreateTimeStart());
        }

        if (queryRequest.getCreateTimeEnd() != null) {
            queryWrapper.le("createTime", queryRequest.getCreateTimeEnd());
        }

        // 添加有效期时间范围查询
        if (queryRequest.getValidUntilStart() != null) {
            queryWrapper.ge("validUntil", queryRequest.getValidUntilStart());
        }

        if (queryRequest.getValidUntilEnd() != null) {
            queryWrapper.le("validUntil", queryRequest.getValidUntilEnd());
        }

        // 添加使用期时间范围查询
        if (queryRequest.getUsedTimeStart() != null) {
            queryWrapper.ge("useAt", queryRequest.getUsedTimeStart());
        }

        if (queryRequest.getUsedTimeEnd() != null) {
            queryWrapper.le("useAt", queryRequest.getUsedTimeEnd());
        }

        queryWrapper.orderBy("createTime", false);
        return queryWrapper;
    }

    /**
     * 获取脱敏的兑换码信息
     * @param vipRedeemCode
     * @return
     */
    @Override
    public VipRedeemCodeVO getVipRedeemCodeVO(VipRedeemCode vipRedeemCode) {
        if (vipRedeemCode == null) {
            return null;
        }

        VipRedeemCodeVO vipRedeemCodeVO = new VipRedeemCodeVO();
        BeanUtil.copyProperties(vipRedeemCode, vipRedeemCodeVO);

        LocalDateTime now = LocalDateTime.now();

        // 设置状态描述
        String status = vipRedeemCode.getStatus();
        switch (status) {
            case "unused":
                vipRedeemCodeVO.setStatusText("未使用");
                break;
            case "used":
                vipRedeemCodeVO.setStatusText("已使用");
                break;
            case "expired":
                vipRedeemCodeVO.setStatusText("已过期");
                break;
            default:
                vipRedeemCodeVO.setStatusText("未知状态");
        }

        // 检查兑换码是否过期并更新状态
        boolean isCodeExpired = VipRedeemCodeStatusEnum.EXPIRED.getValue().equals(vipRedeemCode.getStatus())
                || (vipRedeemCode.getValidUntil() != null && vipRedeemCode.getValidUntil().isBefore(now));

        if (isCodeExpired && VipRedeemCodeStatusEnum.UNUSED.getValue().equals(vipRedeemCode.getStatus())) {
            vipRedeemCodeVO.setStatus(VipRedeemCodeStatusEnum.EXPIRED.getValue());
            vipRedeemCodeVO.setStatusText("已过期");
        }

        // 设置兑换码可用性
        vipRedeemCodeVO.setIsAvailable(!isCodeExpired && VipRedeemCodeStatusEnum.UNUSED.getValue().equals(status));

        // 计算兑换码剩余可用天数
        if (vipRedeemCode.getValidUntil() != null) {
            if (vipRedeemCode.getValidUntil().isAfter(now)) {
                long remainingDays = java.time.temporal.ChronoUnit.DAYS.between(now, vipRedeemCode.getValidUntil());
                vipRedeemCodeVO.setCodeRemainingDays((int) remainingDays);
            } else {
                vipRedeemCodeVO.setCodeRemainingDays(0);
            }
        }

        // 设置VIP时长描述
        Integer vipDuration = vipRedeemCode.getVipDuration();
        if (vipDuration != null) {
            if (vipDuration == 1) {
                vipRedeemCodeVO.setVipDurationText("1天");
            } else if (vipDuration == 7) {
                vipRedeemCodeVO.setVipDurationText("7天");
            } else if (vipDuration == 30) {
                vipRedeemCodeVO.setVipDurationText("30天");
            } else if (vipDuration == 90) {
                vipRedeemCodeVO.setVipDurationText("90天");
            } else if (vipDuration == 365) {
                vipRedeemCodeVO.setVipDurationText("365天（1年）");
            } else if (vipDuration >= 365) {
                int years = vipDuration / 365;
                int days = vipDuration % 365;
                if (days == 0) {
                    vipRedeemCodeVO.setVipDurationText(years + "年");
                } else {
                    vipRedeemCodeVO.setVipDurationText(years + "年" + days + "天");
                }
            } else {
                vipRedeemCodeVO.setVipDurationText(vipDuration + "天");
            }
        }

        // 处理VIP相关信息（仅对已使用的兑换码）
        if (VipRedeemCodeStatusEnum.USED.getValue().equals(status) && vipRedeemCode.getVipExpireTime() != null) {
            LocalDateTime vipExpireTime = vipRedeemCode.getVipExpireTime();

            // 判断VIP是否已过期
            boolean isVipExpired = vipExpireTime.isBefore(now);
            vipRedeemCodeVO.setIsVipExpired(isVipExpired);

            if (!isVipExpired) {
                // VIP未过期，计算剩余天数
                long remainingDays = java.time.temporal.ChronoUnit.DAYS.between(now, vipExpireTime);
                long remainingHours = java.time.temporal.ChronoUnit.HOURS.between(now, vipExpireTime) % 24;

                vipRedeemCodeVO.setVipRemainingDays((int) remainingDays);

                // 设置剩余时间描述
                if (remainingDays > 0) {
                    if (remainingHours > 0) {
                        vipRedeemCodeVO.setVipRemainingText(remainingDays + "天" + remainingHours + "小时");
                    } else {
                        vipRedeemCodeVO.setVipRemainingText(remainingDays + "天");
                    }
                } else if (remainingHours > 0) {
                    vipRedeemCodeVO.setVipRemainingText(remainingHours + "小时");
                } else {
                    long remainingMinutes = java.time.temporal.ChronoUnit.MINUTES.between(now, vipExpireTime);
                    if (remainingMinutes > 0) {
                        vipRedeemCodeVO.setVipRemainingText(remainingMinutes + "分钟");
                    } else {
                        vipRedeemCodeVO.setVipRemainingText("即将过期");
                    }
                }
            } else {
                // VIP已过期
                vipRedeemCodeVO.setVipRemainingDays(0);
                vipRedeemCodeVO.setVipRemainingText("已过期");
            }
        } else {
            // 未使用的兑换码，VIP相关字段为空
            vipRedeemCodeVO.setIsVipExpired(null);
            vipRedeemCodeVO.setVipRemainingDays(null);
            vipRedeemCodeVO.setVipRemainingText(null);
        }

        return vipRedeemCodeVO;
    }

    /**
     * 获取脱敏的兑换码信息列表
     * @param vipRedeemCodeList
     * @return
     */
    @Override
    public List<VipRedeemCodeVO> getVipRedeemCodeVOList(List<VipRedeemCode> vipRedeemCodeList) {
        if (vipRedeemCodeList == null) {
            return new ArrayList<>();
        }
        return vipRedeemCodeList.stream()
                .map(this::getVipRedeemCodeVO)
                .collect(Collectors.toList());
    }

    /**
     * 生成唯一兑换码
     * @return
     */
    @Override
    public String generateUniqueCode() {
        String code;
        int maxAttempts = 10;
        int attempts = 0;

        do {
            code = RandomUtil.randomString("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", 8);
            attempts++;

            if (attempts >= maxAttempts) {
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, "生成唯一兑换码失败，请重试");
            }
        } while (findByCode(code) != null);

        return code;
    }

    /**
     * 更新兑换码
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateExpiredCodes() {
        // 查找所有过期的兑换码
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("status", VipRedeemCodeStatusEnum.UNUSED.getValue())
                .lt("validUntil", LocalDateTime.now());

        List<VipRedeemCode> expiredCodes = this.list(queryWrapper);

        if (!expiredCodes.isEmpty()) {
            // 更新兑换码状态为过期
            VipRedeemCode updateEntity = new VipRedeemCode();
            updateEntity.setStatus(VipRedeemCodeStatusEnum.EXPIRED.getValue());
            updateEntity.setUpdateTime(LocalDateTime.now());

            int count = this.mapper.updateByQuery(updateEntity, queryWrapper);
            log.info("更新了 {} 个过期兑换码的状态", count);
        }

        // 查找所有已使用但VIP已过期的兑换码
        QueryWrapper expiredVipQueryWrapper = new QueryWrapper();
        expiredVipQueryWrapper.eq("status", VipRedeemCodeStatusEnum.USED.getValue())
                .lt("vipExpireTime", LocalDateTime.now())
                .isNotNull("usedByUserId");

        List<VipRedeemCode> expiredVipCodes = this.list(expiredVipQueryWrapper);

        if (!expiredVipCodes.isEmpty()) {
            // 恢复用户角色为普通用户
            for (VipRedeemCode expiredVipCode : expiredVipCodes) {
                if (expiredVipCode.getUsedByUserId() != null) {
                    User user = userService.getById(expiredVipCode.getUsedByUserId());
                    if (user != null && !UserRoleEnum.ADMIN.getValue().equals(user.getUserRole())) {
                        // 只有非管理员用户才需要恢复为普通用户角色
                        User updateUser = new User();
                        updateUser.setId(user.getId());
                        updateUser.setUserRole(UserRoleEnum.USER.getValue());
                        updateUser.setVipRedeemCodeId(null);
                        updateUser.setUpdateTime(LocalDateTime.now());

                        boolean updateResult = userService.updateById(updateUser);
                        if (updateResult) {
                            log.info("用户 {} 的VIP已过期，已恢复为普通用户角色", user.getId());
                        } else {
                            log.error("恢复用户 {} 角色失败", user.getId());
                        }
                    }
                }
            }
        }
    }

    /**
     * 根据兑换码查询
     * @param code
     * @return
     */
    @Override
    public VipRedeemCode findByCode(String code) {
        if (StrUtil.isBlank(code)) {
            return null;
        }

        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("code", code);
        return this.getOne(queryWrapper);
    }

    /**
     * 兑换VIP
     * @param user 当前用户
     * @param vipCode 兑换码
     * @return 是否兑换成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized boolean exchangeVip(User user, String vipCode) {
        // 参数校验
        if (user == null || StrUtil.isBlank(vipCode)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数不能为空");
        }

        if (vipCode.length() != 8) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "兑换码格式不正确");
        }

        // 检查用户是否已经使用过这个兑换码
        if (user.getVipRedeemCodeId() != null) {
            VipRedeemCode currentVipCode = this.getById(user.getVipRedeemCodeId());
            if (currentVipCode != null && vipCode.equals(currentVipCode.getCode())) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "兑换码已经使用过，请使用其他兑换码");
            }
        }

        // 从数据库查找兑换码
        VipRedeemCode redeemCode = findByCode(vipCode);
        if (redeemCode == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "兑换码不存在");
        }

        // 检查兑换码状态
        if (VipRedeemCodeStatusEnum.USED.getValue().equals(redeemCode.getStatus())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "兑换码已被使用");
        }

        if (VipRedeemCodeStatusEnum.EXPIRED.getValue().equals(redeemCode.getStatus())
                || redeemCode.getValidUntil().isBefore(LocalDateTime.now())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "兑换码已过期");
        }

        try {
            // 计算VIP过期时间
            LocalDateTime vipExpireTime;
            int vipDuration = redeemCode.getVipDuration() != null ? redeemCode.getVipDuration() : 365;

            // 检查用户当前是否有VIP
            if (user.getVipRedeemCodeId() != null) {
                VipRedeemCode currentVipCode = this.getById(user.getVipRedeemCodeId());
                if (currentVipCode != null && currentVipCode.getVipExpireTime() != null &&
                        currentVipCode.getVipExpireTime().isAfter(LocalDateTime.now())) {
                    // 在现有VIP基础上延期
                    vipExpireTime = currentVipCode.getVipExpireTime().plusDays(vipDuration);
                } else {
                    // 从现在开始计算
                    vipExpireTime = LocalDateTime.now().plusDays(vipDuration);
                }
            } else {
                // 首次开通VIP
                vipExpireTime = LocalDateTime.now().plusDays(vipDuration);
            }

            // 生成VIP编号
            Long vipNumber = System.currentTimeMillis() * 1000 + user.getId();

            // 更新兑换码状态
            VipRedeemCode updateRedeemCode = new VipRedeemCode();
            updateRedeemCode.setId(redeemCode.getId());
            updateRedeemCode.setStatus(VipRedeemCodeStatusEnum.USED.getValue());
            updateRedeemCode.setUsedAt(LocalDateTime.now());
            updateRedeemCode.setUsedBy(user.getUserAccount());
            updateRedeemCode.setUsedByUserId(user.getId());
            updateRedeemCode.setVipExpireTime(vipExpireTime);
            updateRedeemCode.setVipNumber(vipNumber);
            updateRedeemCode.setUpdateTime(LocalDateTime.now());

            boolean updateCodeResult = this.updateById(updateRedeemCode);
            if (!updateCodeResult) {
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, "更新兑换码状态失败");
            }

            // 更新用户信息
            User updateUser = new User();
            updateUser.setId(user.getId());
            updateUser.setVipRedeemCodeId(redeemCode.getId());

            if (UserRoleEnum.ADMIN.getValue().equals(user.getUserRole())) {
                updateUser.setUserRole(UserRoleEnum.ADMIN.getValue());
                log.info("管理员用户 {} 使用兑换码延期VIP时间，保持管理员角色", user.getId());
            } else {
                updateUser.setUserRole(UserRoleEnum.VIP.getValue());
            }

            boolean updateUserResult = userService.updateById(updateUser);
            if (!updateUserResult) {
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, "更新用户信息失败");
            }

            log.info("用户 {} 成功使用兑换码 {} 开通VIP，过期时间：{}",
                    user.getId(), vipCode, vipExpireTime);
            return true;

        } catch (Exception e) {
            log.error("VIP兑换失败，用户：{}，兑换码：{}", user.getId(), vipCode, e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "VIP兑换失败，请重试");
        }
    }

    /**
     * VIP续费（正确的覆盖逻辑）
     * 使用新的兑换码进行续费，覆盖用户当前的兑换码关联，累加VIP时间
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized boolean renewVip(User user, String vipCode) {
        // 参数校验
        if (user == null || StrUtil.isBlank(vipCode)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数不能为空");
        }

        if (vipCode.length() != 8) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "兑换码格式不正确");
        }

        // 检查用户是否已经使用过这个相同的兑换码
        VipRedeemCode existingCode = findByCode(vipCode);
        if (existingCode != null && user.getId().equals(existingCode.getUsedByUserId())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "不能重复使用同一个兑换码");
        }

        // 从数据库查找新的兑换码
        VipRedeemCode newRedeemCode = findByCode(vipCode);
        if (newRedeemCode == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "兑换码不存在");
        }

        // 检查新兑换码状态
        if (VipRedeemCodeStatusEnum.USED.getValue().equals(newRedeemCode.getStatus())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "兑换码已被使用");
        }

        if (VipRedeemCodeStatusEnum.EXPIRED.getValue().equals(newRedeemCode.getStatus())
                || newRedeemCode.getValidUntil().isBefore(LocalDateTime.now())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "兑换码已过期");
        }

        try {
            // 获取用户当前的VIP过期时间
            LocalDateTime currentVipExpireTime = null;
            if (user.getVipRedeemCodeId() != null) {
                VipRedeemCode currentVipCode = this.getById(user.getVipRedeemCodeId());
                if (currentVipCode != null && currentVipCode.getVipExpireTime() != null) {
                    currentVipExpireTime = currentVipCode.getVipExpireTime();
                }
            }

            // 计算续费后的VIP过期时间
            LocalDateTime newVipExpireTime;
            int newVipDuration = newRedeemCode.getVipDuration() != null ? newRedeemCode.getVipDuration() : 365;

            if (currentVipExpireTime != null && currentVipExpireTime.isAfter(LocalDateTime.now())) {
                // 在现有VIP基础上延期
                newVipExpireTime = currentVipExpireTime.plusDays(newVipDuration);
                log.info("用户 {} 续费VIP，在现有过期时间 {} 基础上延长 {} 天",
                        user.getId(), currentVipExpireTime, newVipDuration);
            } else {
                // VIP已过期或首次开通，从现在开始计算
                newVipExpireTime = LocalDateTime.now().plusDays(newVipDuration);
                log.info("用户 {} 续费VIP，从当前时间开始计算 {} 天", user.getId(), newVipDuration);
            }

            // 生成新的VIP编号
            Long newVipNumber = System.currentTimeMillis() * 1000 + user.getId();

            // 更新新兑换码的状态
            VipRedeemCode updateNewRedeemCode = new VipRedeemCode();
            updateNewRedeemCode.setId(newRedeemCode.getId());
            updateNewRedeemCode.setStatus(VipRedeemCodeStatusEnum.USED.getValue());
            updateNewRedeemCode.setUsedAt(LocalDateTime.now());
            updateNewRedeemCode.setUsedBy(user.getUserAccount());
            updateNewRedeemCode.setUsedByUserId(user.getId());
            updateNewRedeemCode.setVipExpireTime(newVipExpireTime);
            updateNewRedeemCode.setVipNumber(newVipNumber);
            updateNewRedeemCode.setUpdateTime(LocalDateTime.now());

            boolean updateNewCodeResult = this.updateById(updateNewRedeemCode);
            if (!updateNewCodeResult) {
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, "更新新兑换码状态失败");
            }

            // 关键：覆盖用户的兑换码关联（正确的续费逻辑）
            User updateUser = new User();
            updateUser.setId(user.getId());
            updateUser.setVipRedeemCodeId(newRedeemCode.getId()); // 覆盖为新的兑换码ID

            // 设置用户角色
            if (UserRoleEnum.ADMIN.getValue().equals(user.getUserRole())) {
                updateUser.setUserRole(UserRoleEnum.ADMIN.getValue());
                log.info("管理员用户 {} 续费VIP，保持管理员角色", user.getId());
            } else {
                updateUser.setUserRole(UserRoleEnum.VIP.getValue());
            }

            updateUser.setUpdateTime(LocalDateTime.now());

            boolean updateUserResult = userService.updateById(updateUser);
            if (!updateUserResult) {
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, "更新用户信息失败");
            }

            log.info("用户 {} 成功续费VIP，使用兑换码 {}，新的过期时间：{}",
                    user.getId(), vipCode, newVipExpireTime);
            log.info("用户兑换码关联已从旧兑换码覆盖为新兑换码ID: {}", newRedeemCode.getId());

            return true;

        } catch (Exception e) {
            log.error("VIP续费失败，用户：{}，兑换码：{}", user.getId(), vipCode, e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "VIP续费失败，请重试");
        }
    }

    /**
     * 获取用户VIP使用历史（通过兑换码表查询该用户使用过的所有兑换码）
     */
    @Override
    public List<VipRedeemCodeVO> getUserVipHistory(Long userId) {
        if (userId == null) {
            return new ArrayList<>();
        }

        // 查询用户使用过的所有兑换码（通过usedByUserId字段）
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("usedByUserId", userId)
                .eq("status", VipRedeemCodeStatusEnum.USED.getValue())
                .orderBy("usedAt", false); // 按使用时间倒序

        List<VipRedeemCode> userVipCodes = this.list(queryWrapper);

        // 转换为VO对象
        List<VipRedeemCodeVO> vipHistoryList = new ArrayList<>();
        for (VipRedeemCode vipCode : userVipCodes) {
            VipRedeemCodeVO vipCodeVO = getVipRedeemCodeVO(vipCode);
            if (vipCodeVO != null) {
                vipHistoryList.add(vipCodeVO);
            }
        }

        log.info("获取用户 {} 的VIP使用历史，共 {} 条记录", userId, vipHistoryList.size());
        return vipHistoryList;
    }

    /**
     * 获取用户VIP剩余天数
     */
    @Override
    public int getUserVipRemainingDays(Long userId) {
        User user = userService.getById(userId);
        if (user == null || user.getVipRedeemCodeId() == null) {
            return -1;
        }

        VipRedeemCode vipCode = this.getById(user.getVipRedeemCodeId());
        if (vipCode == null || vipCode.getVipExpireTime() == null) {
            return -1;
        }

        LocalDateTime now = LocalDateTime.now();
        if (vipCode.getVipExpireTime().isBefore(now)) {
            return 0; // 已过期
        }

        return (int) java.time.temporal.ChronoUnit.DAYS.between(now, vipCode.getVipExpireTime());
    }

    /**
     * 获取脱敏的已登录用户信息，包含VIP信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public LoginUserVO getLoginUserVOWithVipInfo(User user) {
        if (user == null) {
            return null;
        }

        LoginUserVO loginUserVO = new LoginUserVO();
        BeanUtil.copyProperties(user, loginUserVO);

        // 如果用户有关联的VIP兑换码，获取VIP信息
        if (user.getVipRedeemCodeId() != null) {
            VipRedeemCode vipRedeemCode = this.getById(user.getVipRedeemCodeId());

            // 检查兑换码是否被删除
            if (vipRedeemCode == null) {
                // 兑换码被删除，恢复用户状态
                if (!UserRoleEnum.ADMIN.getValue().equals(user.getUserRole())) {
                    User updateUser = new User();
                    updateUser.setId(user.getId());
                    updateUser.setUserRole(UserRoleEnum.USER.getValue());
                    updateUser.setVipRedeemCodeId(null);
                    updateUser.setUpdateTime(LocalDateTime.now());

                    boolean updateResult = userService.updateById(updateUser);
                    if (updateResult) {
                        log.info("登录时发现用户 {} 关联的兑换码已被删除，已恢复为普通用户角色", user.getId());
                        // 更新返回的VO对象
                        loginUserVO.setUserRole(UserRoleEnum.USER.getValue());
                        loginUserVO.setVipRedeemCodeId(null);
                    } else {
                        log.error("恢复用户 {} 角色失败", user.getId());
                    }
                }
                loginUserVO.setIsVip(false);
                return loginUserVO;
            }

            // 检查VIP是否过期
            boolean isVipExpired = vipRedeemCode.getVipExpireTime() == null ||
                    vipRedeemCode.getVipExpireTime().isBefore(LocalDateTime.now());

            if (isVipExpired) {
                // VIP已过期，恢复用户状态
                if (!UserRoleEnum.ADMIN.getValue().equals(user.getUserRole())) {
                    User updateUser = new User();
                    updateUser.setId(user.getId());
                    updateUser.setUserRole(UserRoleEnum.USER.getValue());
                    updateUser.setVipRedeemCodeId(null);
                    updateUser.setUpdateTime(LocalDateTime.now());

                    boolean updateResult = userService.updateById(updateUser);
                    if (updateResult) {
                        log.info("登录时发现用户 {} 的VIP已过期，已恢复为普通用户角色", user.getId());
                        // 更新返回的VO对象
                        loginUserVO.setUserRole(UserRoleEnum.USER.getValue());
                        loginUserVO.setVipRedeemCodeId(null);
                    } else {
                        log.error("恢复用户 {} 角色失败", user.getId());
                    }
                }
                loginUserVO.setVipRemainingDays(0);
                loginUserVO.setIsVip(false);
            } else {
                // VIP有效，设置VIP信息
                loginUserVO.setCurrentVipCode(vipRedeemCode.getCode());
                loginUserVO.setVipExpireTime(vipRedeemCode.getVipExpireTime());
                loginUserVO.setVipNumber(vipRedeemCode.getVipNumber());

                // 计算VIP剩余天数
                LocalDateTime now = LocalDateTime.now();
                int remainingDays = (int) java.time.temporal.ChronoUnit.DAYS.between(now, vipRedeemCode.getVipExpireTime());
                loginUserVO.setVipRemainingDays(remainingDays);
                loginUserVO.setIsVip(true);
            }
        } else {
            loginUserVO.setIsVip(false);
        }

        return loginUserVO;
    }

    /**
     * 恢复用户状态（当兑换码被删除时调用）
     * @param redeemCodeId 兑换码ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void restoreUserStatusByRedeemCodeId(Long redeemCodeId) {
        if (redeemCodeId == null) {
            return;
        }

        // 查找使用该兑换码的用户
        QueryWrapper userQueryWrapper = new QueryWrapper();
        userQueryWrapper.eq("vipRedeemCodeId", redeemCodeId);
        List<User> users = userService.list(userQueryWrapper);

        for (User user : users) {
            if (!UserRoleEnum.ADMIN.getValue().equals(user.getUserRole())) {
                // 只有非管理员用户才需要恢复为普通用户角色
                User updateUser = new User();
                updateUser.setId(user.getId());
                updateUser.setUserRole(UserRoleEnum.USER.getValue());
                updateUser.setVipRedeemCodeId(null);
                updateUser.setUpdateTime(LocalDateTime.now());

                boolean updateResult = userService.updateById(updateUser);
                if (updateResult) {
                    log.info("兑换码 {} 被删除，用户 {} 已恢复为普通用户角色", redeemCodeId, user.getId());
                } else {
                    log.error("恢复用户 {} 角色失败", user.getId());
                }
            }
        }
    }

    /**
     * 批量恢复用户状态（当兑换码被批量删除时调用）
     * @param redeemCodeIds 兑换码ID列表
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchRestoreUserStatusByRedeemCodeIds(List<Long> redeemCodeIds) {
        if (redeemCodeIds == null || redeemCodeIds.isEmpty()) {
            return;
        }

        for (Long redeemCodeId : redeemCodeIds) {
            restoreUserStatusByRedeemCodeId(redeemCodeId);
        }
    }

    /**
     * 更新VIP兑换码并同时处理用户状态
     * @param updateRequest 更新请求
     * @return 是否更新成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateVipRedeemCodeWithUserStatus(VipRedeemCodeUpdateRequest updateRequest) {
        if (updateRequest == null || updateRequest.getId() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "更新参数不能为空");
        }

        // 获取原兑换码信息
        VipRedeemCode existingCode = this.getById(updateRequest.getId());
        if (existingCode == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "兑换码不存在");
        }

        // 构建更新实体
        VipRedeemCode updateEntity = new VipRedeemCode();
        updateEntity.setId(updateRequest.getId());
        updateEntity.setValidUntil(updateRequest.getValidUntil());
        updateEntity.setRemark(updateRequest.getRemark());
        updateEntity.setVipDuration(updateRequest.getVipDuration());
        updateEntity.setUpdateTime(LocalDateTime.now());

        // 判断是否需要更新状态
        boolean shouldExpire = false;
        if (updateRequest.getValidUntil() != null && updateRequest.getValidUntil().isBefore(LocalDateTime.now())) {
            updateEntity.setStatus(VipRedeemCodeStatusEnum.EXPIRED.getValue());
            shouldExpire = true;
        } else if (updateRequest.getValidUntil() != null && VipRedeemCodeStatusEnum.EXPIRED.getValue().equals(existingCode.getStatus())) {
            // 如果之前是过期状态，但现在设置了未来时间，则恢复为未使用状态（如果没有被使用过）
            if (!VipRedeemCodeStatusEnum.USED.getValue().equals(existingCode.getStatus())) {
                updateEntity.setStatus(VipRedeemCodeStatusEnum.UNUSED.getValue());
            }
        }

        // 更新兑换码
        boolean updateResult = this.updateById(updateEntity);
        if (!updateResult) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "更新兑换码失败");
        }

        // 如果兑换码被设置为过期，或者VIP过期时间被修改为过去的时间，需要处理用户状态
        if (shouldExpire || isVipExpiredByUpdate(existingCode, updateRequest)) {
            handleUserStatusWhenVipExpired(updateRequest.getId());
        }

        log.info("管理员更新兑换码 {} 成功，同时处理了用户状态", updateRequest.getId());
        return true;
    }

    /**
     * 强制过期兑换码并取消用户VIP权限
     * @param redeemCodeId 兑换码ID
     * @return 操作是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean forceExpireRedeemCode(Long redeemCodeId) {
        if (redeemCodeId == null || redeemCodeId <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "兑换码ID不能为空");
        }

        // 获取兑换码信息
        VipRedeemCode redeemCode = this.getById(redeemCodeId);
        if (redeemCode == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "兑换码不存在");
        }

        // 如果兑换码已经是过期状态，直接返回成功
        if (VipRedeemCodeStatusEnum.EXPIRED.getValue().equals(redeemCode.getStatus())) {
            log.info("兑换码 {} 已经是过期状态，无需重复操作", redeemCodeId);
            return true;
        }

        try {
            // 如果兑换码正在被使用，需要先取消用户的VIP权限
            if (VipRedeemCodeStatusEnum.USED.getValue().equals(redeemCode.getStatus()) &&
                    redeemCode.getUsedByUserId() != null) {

                User user = userService.getById(redeemCode.getUsedByUserId());
                if (user != null) {
                    // 恢复用户为普通用户（管理员除外）
                    if (!UserRoleEnum.ADMIN.getValue().equals(user.getUserRole())) {
                        User updateUser = new User();
                        updateUser.setId(user.getId());
                        updateUser.setUserRole(UserRoleEnum.USER.getValue());
                        updateUser.setVipRedeemCodeId(null);
                        updateUser.setUpdateTime(LocalDateTime.now());

                        boolean updateUserResult = userService.updateById(updateUser);
                        if (updateUserResult) {
                            log.info("强制过期兑换码 {}，用户 {} 的VIP权限已被取消", redeemCodeId, user.getId());
                        } else {
                            log.error("取消用户 {} 的VIP权限失败", user.getId());
                        }
                    } else {
                        log.info("用户 {} 是管理员，保持管理员角色，仅清除VIP兑换码关联", user.getId());
                        User updateUser = new User();
                        updateUser.setId(user.getId());
                        updateUser.setVipRedeemCodeId(null);
                        updateUser.setUpdateTime(LocalDateTime.now());
                        userService.updateById(updateUser);
                    }
                }
            }

            // 更新兑换码状态为过期
            VipRedeemCode updateRedeemCode = new VipRedeemCode();
            updateRedeemCode.setId(redeemCodeId);
            updateRedeemCode.setStatus(VipRedeemCodeStatusEnum.EXPIRED.getValue());
            updateRedeemCode.setUpdateTime(LocalDateTime.now());

            boolean result = this.updateById(updateRedeemCode);
            if (result) {
                log.info("管理员强制过期兑换码 {} 成功", redeemCodeId);
            } else {
                log.error("强制过期兑换码 {} 失败", redeemCodeId);
            }

            return result;

        } catch (Exception e) {
            log.error("强制过期兑换码 {} 时发生异常", redeemCodeId, e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "强制过期兑换码失败");
        }
    }

    /**
     * 批量强制过期兑换码并取消用户VIP权限
     * @param redeemCodeIds 兑换码ID列表
     * @return 操作是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchForceExpireRedeemCodes(List<Long> redeemCodeIds) {
        if (redeemCodeIds == null || redeemCodeIds.isEmpty()) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "兑换码ID列表不能为空");
        }

        // 检查所有兑换码是否存在
        List<VipRedeemCode> existingCodes = this.listByIds(redeemCodeIds);
        if (existingCodes.size() != redeemCodeIds.size()) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "部分兑换码不存在");
        }

        int successCount = 0;
        List<String> failedCodes = new ArrayList<>();

        for (Long redeemCodeId : redeemCodeIds) {
            try {
                boolean result = forceExpireRedeemCode(redeemCodeId);
                if (result) {
                    successCount++;
                } else {
                    failedCodes.add(String.valueOf(redeemCodeId));
                }
            } catch (Exception e) {
                log.error("批量强制过期兑换码时，兑换码 {} 操作失败", redeemCodeId, e);
                failedCodes.add(String.valueOf(redeemCodeId));
            }
        }

        if (!failedCodes.isEmpty()) {
            log.warn("批量强制过期兑换码部分失败，失败的兑换码ID: {}", String.join(", ", failedCodes));
        }

        log.info("批量强制过期兑换码完成，成功: {}, 失败: {}", successCount, failedCodes.size());

        // 只要有成功的就返回true，失败的已经记录日志
        return successCount > 0;
    }

    /**
     * 判断VIP是否因为更新而过期
     * @param existingCode 原兑换码
     * @param updateRequest 更新请求
     * @return 是否过期
     */
    private boolean isVipExpiredByUpdate(VipRedeemCode existingCode, VipRedeemCodeUpdateRequest updateRequest) {
        // 如果兑换码已被使用，并且原来有VIP过期时间
        if (VipRedeemCodeStatusEnum.USED.getValue().equals(existingCode.getStatus())
                && existingCode.getVipExpireTime() != null) {

            // 如果更新请求中的有效期比原VIP过期时间早，说明VIP被强制过期
            if (updateRequest.getValidUntil() != null
                    && updateRequest.getValidUntil().isBefore(existingCode.getVipExpireTime())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 处理VIP过期时的用户状态
     * @param redeemCodeId 兑换码ID
     */
    private void handleUserStatusWhenVipExpired(Long redeemCodeId) {
        // 查找使用该兑换码的用户
        QueryWrapper userQueryWrapper = new QueryWrapper();
        userQueryWrapper.eq("vipRedeemCodeId", redeemCodeId);
        List<User> users = userService.list(userQueryWrapper);

        for (User user : users) {
            if (!UserRoleEnum.ADMIN.getValue().equals(user.getUserRole())) {
                // 只有非管理员用户才需要恢复为普通用户角色
                User updateUser = new User();
                updateUser.setId(user.getId());
                updateUser.setUserRole(UserRoleEnum.USER.getValue());
                updateUser.setVipRedeemCodeId(null);
                updateUser.setUpdateTime(LocalDateTime.now());

                boolean updateUserResult = userService.updateById(updateUser);
                if (updateUserResult) {
                    log.info("兑换码 {} 被管理员强制过期，用户 {} 已恢复为普通用户角色", redeemCodeId, user.getId());
                } else {
                    log.error("恢复用户 {} 角色失败", user.getId());
                }
            }
        }
    }
}
